package com.xinhe.cn.cpbox.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpUtil;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.xinhe.cn.cpbox.entity.dto.PayDto;
import com.xinhe.cn.cpbox.entity.po.MatchMaker;
import com.xinhe.cn.cpbox.entity.po.UserInfo;
import com.xinhe.cn.cpbox.entity.po.UserOrder;
import com.xinhe.cn.cpbox.mapper.MatchMakerMapper;
import com.xinhe.cn.cpbox.mapper.UserInfoMapper;
import com.xinhe.cn.cpbox.mapper.UserOrderMapper;
import com.xinhe.cn.cpbox.payutils.WXPayParms;
import com.xinhe.cn.cpbox.payutils.WXPayUtil;
import com.xinhe.cn.cpbox.service.PayService;
import com.xinhe.cn.cpbox.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * @author HB
 * @date 2021/10/09 11:37
 */
@Slf4j
@Service
public class PayServiceImpl implements PayService {
    @Autowired
    UserOrderMapper userOrderMapper;
    @Autowired
    MatchMakerMapper matchMakerMapper;
    @Autowired
    UserInfoMapper userInfoMapper;

    @Override
    public Map<String, String> getOrder(HttpServletRequest request, PayDto payDto) {
        // 获取各类参数
        String openId = payDto.getOpenId();
        String money = payDto.getMoney();
        String orderName = payDto.getOrderName();

        if (StringUtils.isBlank(openId) || StringUtils.isBlank(money)) {
            return null;
        }
        try {
            // 获取商品名
            if (StringUtils.isBlank(orderName)) {
                orderName = "cp盲盒";  // 默认
            }

            // 拼接统一下单地址参数
            Map<String, String> paraMap = new HashMap<String, String>();
            // 获取ip地址
            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            if (ip.indexOf(",") != -1) {
                String[] ips = ip.split(",");
                ip = ips[0].trim();
            }

            String out_trade_no = UUID.randomUUID().toString().replaceAll("-", "");
            paraMap.put("appid", WXPayParms.PUBLIC_APPID);
            paraMap.put("body", orderName);
            paraMap.put("mch_id", WXPayParms.MCHID);
            paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
            paraMap.put("openid", openId);
            paraMap.put("out_trade_no", out_trade_no);//订单号
            paraMap.put("spbill_create_ip", ip);
            paraMap.put("total_fee", money);
            paraMap.put("trade_type", "JSAPI");
            paraMap.put("sign_type", WxPayConstants.SignType.MD5);
            paraMap.put("notify_url", WXPayParms.NOTIFY_URL);

            String sign = WXPayUtil.generateSignature(paraMap, WXPayParms.PATERNER_KEY);
            paraMap.put("sign", sign);
            String xml = WXPayUtil.mapToXml(paraMap);
            // 拼接好参数，调用统一支付接口
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            // 发送post请求"统一下单接口"返回预支付id:prepay_id
            String xmlStr = HttpUtil.post(unifiedorder_url, xml);
//            log.info(xmlStr);

            // 以下内容是返回前端页面的json数据
            String prepay_id = "";//预支付id
            String signStr = "";
            if (xmlStr.contains("SUCCESS")) {
                Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                prepay_id = (String) map.get("prepay_id");
                signStr = map.get("sign");
            }

            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", WXPayParms.PUBLIC_APPID);
            payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("signType", WxPayConstants.SignType.MD5);
            payMap.put("package", "prepay_id=" + prepay_id);
            String paySign = WXPayUtil.generateSignature(payMap, WXPayParms.PATERNER_KEY);
            payMap.put("paySign", paySign);
            payMap.put("out_trade_no", out_trade_no);
//            paraMap.put("signStr",signStr);
            if (StringUtils.isNotEmpty(prepay_id)) {
                UserOrder userOrder = new UserOrder();
                userOrder.setCreateTime(DateUtils.getNowDate());
                // 将钱转化为元
                BigDecimal amountPay = (new BigDecimal(money).divide(new BigDecimal("100"))).setScale(2);
                userOrder.setMoney(amountPay.toString());
                userOrder.setOrderId(out_trade_no);
                userOrder.setOrderName(orderName);
                userOrder.setOrderType("JSAPI");
                userOrder.setIsPay("0");
                // 设置openid
                userOrder.setOpenId(openId);

                // 存入数据库
                userOrderMapper.insert(userOrder);
            }
            return payMap;
        } catch (Exception e) {
            log.error("H5预支付接口报错", e);
            return null;
        }
    }

    @Transactional
    @Override
    public String callBack(HttpServletRequest request, HttpServletResponse response) {
        InputStream is = null;
        String xml = null;
        try {
            is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
            xml = IoUtil.read(is, "UTF-8");
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map
            log.info(">>>>微信支付回调开始...<<<<");
            String out_trade_no = notifyMap.get("out_trade_no");
            String return_code = notifyMap.get("return_code");
            if (return_code.equals("SUCCESS")) {
                log.info(">>>>微信支付调起成功...<<<<");
                //查询流水中的金额
                String total_fee = notifyMap.get("total_fee");
                log.info("支付的金额" + total_fee);
                log.info("支付的订单号" + out_trade_no);

                /*异步回调成功，修改订单状态*/
                UserOrder userOrder = userOrderMapper.findByOrderId(out_trade_no);
                if (Objects.isNull(userOrder)) {
                    log.error("支付回调函数查找不到订单");
                    log.error("xml: " + xml);
                    return null;
                }

                // 对之前未付款的订单进行处理
                if ("0".equals(userOrder.getIsPay())) {
                    log.info("开始处理该订单");
                    // 设置已经支付
                    userOrder.setIsPay("1");
                    userOrderMapper.updateById(userOrder);

                    // 注册月老
                    if (userOrder.getOrderName().equals("成为月老")) {
                        String openId = userOrder.getOpenId();

                        // 查看本人是否为月老(防止重复处理数据)
                        MatchMaker matchMaker = matchMakerMapper.selectById(userOrder.getOpenId());
                        if(Objects.isNull(matchMaker)) {
                            // 查询本人信息
                            UserInfo userInfo = userInfoMapper.selectById(openId);

                            matchMaker = new MatchMaker();
                            matchMaker.setMatchMakerId(openId);
                            // 存在上级
                            if(StringUtils.isNotBlank(userInfo.getExtendId())) {
                                String parentId = userInfo.getExtendId();   // 上级的openId
                                matchMaker.setParentId(parentId);
                                // 上级月老的下级月老数 + 1
                                matchMakerMapper.addChildNum(parentId, 1);

                                // 查询上上级
                                UserInfo parent = userInfoMapper.selectById(parentId);  // 上上级的个人信息
                                // 存在上上级
                                if(!Objects.isNull(parent) && StringUtils.isNotBlank(parent.getExtendId())) {
                                    matchMaker.setGrandparentId(parent.getExtendId());
                                    // 下下级月老数 + 1
                                    matchMakerMapper.addGrandchildNum(parent.getExtendId(), 1);
                                }
                            }
                            matchMaker.setCreateTime(DateUtil.now());
                            matchMaker.setTotalMoney(new BigDecimal(0));
                            matchMaker.setLeftMoney(new BigDecimal(0));
                            matchMaker.setChildNum(0);
                            matchMaker.setGrandchildNum(0);
                            matchMaker.setUserNum(0);
                            matchMaker.setHasApply("0");

                            matchMakerMapper.insert(matchMaker);
                        }
                    }
                } else {
                    log.info("该订单之前已完成处理");
                }

                log.info(">>>>微信异步回调完毕...<<<<");
                response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
            }
        } catch (Exception e) {
            log.error("支付回调函数报错", e);
            log.error("xml: " + xml);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}
